home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / daemons / nfs / nfs-serv.2be / nfs-serv / nfs-server-2.2beta16 / rpcmisc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-20  |  4.5 KB  |  193 lines

  1. /*
  2.  * rpcmisc    Miscellaneous functions for RPC startup and shutdown.
  3.  *        This code is partially snarfed from rpcgen -s tcp -s udp,
  4.  *        partly written by Mark Shand, Donald Becker, and Rick 
  5.  *        Sladkey. It was tweaked slightly by Olaf Kirch to be
  6.  *        useable by both nfsd and mountd.
  7.  *
  8.  *        This software may be used for any purpose provided
  9.  *        the above copyright notice is retained.  It is supplied
  10.  *        as is, with no warranty expressed or implied.
  11.  */
  12.  
  13. #include "system.h"
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <rpc/pmap_clnt.h> 
  17. #include <string.h> 
  18. #include <signal.h>
  19. #include <sys/ioctl.h> 
  20. #include <sys/types.h> 
  21. #include <sys/stat.h> 
  22. #include <fcntl.h> 
  23. #include <memory.h>
  24. #include <sys/socket.h>
  25. #include <netinet/in.h>
  26. #include "rpcmisc.h"
  27. #include "logging.h"
  28.  
  29. static _PRO (void closedown,     (int sig)                );
  30. static _PRO (int makesock,    (int port, int proto, int socksz)    );
  31.  
  32. #define _RPCSVC_CLOSEDOWN    120
  33. int    _rpcpmstart = 0;
  34. int    _rpcfdtype = 0;
  35. int    _rpcsvcdirty = 0;
  36.  
  37. void
  38. rpc_init(name, prog, vers, dispatch, defport, bufsiz)
  39. char    *name;
  40. int    prog;
  41. int    vers;
  42. void    (*dispatch)();
  43. int    defport;
  44. int    bufsiz;
  45. {
  46.     struct sockaddr_in saddr;
  47.     SVCXPRT    *transp;
  48.     int    sock;
  49.     int    asize;
  50.  
  51.     asize = sizeof(saddr);
  52.     sock = 0;
  53.     _rpcfdtype = 0;
  54.     if (getsockname(0, (struct sockaddr *) &saddr, &asize) == 0) {
  55.         int ssize = sizeof (int);
  56.         if (saddr.sin_family != AF_INET)
  57.             exit(1);
  58.         if (getsockopt(0, SOL_SOCKET, SO_TYPE,
  59.                 (char *)&_rpcfdtype, &ssize) == -1)
  60.             exit(1);
  61.         _rpcpmstart = 1;
  62.     } else {
  63.         pmap_unset(prog, vers);
  64.         sock = RPC_ANYSOCK;
  65.     }
  66.  
  67.     if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) {
  68.         if (_rpcfdtype == 0 && defport != 0 &&
  69.             ((sock = makesock(defport, IPPROTO_UDP, bufsiz)) < 0)) {
  70.             fprintf(stderr, "%s: could not make a UDP socket\n",
  71.                     name);
  72.             exit(1);
  73.         }
  74.         transp = svcudp_create(sock);
  75.         if (transp == NULL) {
  76.             fprintf(stderr, "cannot create udp service.");
  77.             exit(1);
  78.         }
  79.         if (!svc_register(transp, prog, vers, dispatch, IPPROTO_UDP)) {
  80.             fprintf(stderr, "unable to register (%s, %d, udp).",
  81.                     name, vers);
  82.             exit(1);
  83.         }
  84.     }
  85.  
  86.     if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) {
  87.         if (_rpcfdtype == 0 && defport != 0 &&
  88.             ((sock = makesock(defport, IPPROTO_TCP, bufsiz)) < 0)) {
  89.             fprintf(stderr, "%s: could not make a TCP socket\n",
  90.                     name);
  91.             exit(1);
  92.         }
  93.         transp = svctcp_create(sock, 0, 0);
  94.         if (transp == NULL) {
  95.             fprintf(stderr, "cannot create tcp service.");
  96.             exit(1);
  97.         }
  98.         if (!svc_register(transp, prog, vers, dispatch, IPPROTO_TCP)) {
  99.             fprintf(stderr, "unable to register (%s, %d, tcp).",
  100.                     name, vers);
  101.             exit(1);
  102.         }
  103.     }
  104.  
  105.     if (_rpcpmstart) {
  106.         signal (SIGALRM, closedown);
  107.         alarm (_RPCSVC_CLOSEDOWN);
  108.     }
  109.  
  110.     /* We ignore SIGPIPE. This is a somewhat dubious method to help
  111.      * an obscure problem with mountd or nfsd dying mysteriously
  112.      * after receiving a SIGHUP. This hopefully makes the problem
  113.      * go away, although I have no idea what causes it.
  114.      */
  115.     {
  116.         struct sigaction pipeact = { SIG_IGN, 0, 0, NULL };
  117.  
  118.         sigaction(SIGPIPE, &pipeact, NULL);
  119.     }
  120. }
  121.  
  122. static void closedown(sig)
  123. int sig;
  124. {
  125.     (void) signal(sig, closedown);
  126.     if (_rpcsvcdirty == 0) {
  127.         extern fd_set svc_fdset;
  128.         static int size;
  129.         int i, openfd;
  130.  
  131.         if (_rpcfdtype == SOCK_DGRAM)
  132.             exit(0);
  133.         if (size == 0) {
  134.             size = getdtablesize();
  135.         }
  136.         for (i = 0, openfd = 0; i < size && openfd < 2; i++)
  137.             if (FD_ISSET(i, &svc_fdset))
  138.                 openfd++;
  139.         if (openfd <= 1)
  140.             exit(0);
  141.     }
  142.     (void) alarm(_RPCSVC_CLOSEDOWN);
  143. }
  144.  
  145. static int makesock(port, proto, socksz)
  146. int port;
  147. int proto;
  148. int socksz;
  149. {
  150.     struct sockaddr_in sin;
  151.     int    s;
  152.     int    sock_type;
  153.     int    val;
  154.  
  155.     sock_type = (proto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
  156.     s = socket(AF_INET, sock_type, proto);
  157.     if (s < 0) {
  158.         dprintf(L_ERROR, "Could not make a socket: %s\n",
  159.                     strerror(errno));
  160.         return (-1);
  161.     }
  162.     memset((char *) &sin, 0, sizeof(sin));
  163.     sin.sin_family = AF_INET;
  164.     sin.sin_addr.s_addr = INADDR_ANY;
  165.     sin.sin_port = htons(port);
  166.  
  167. #ifdef DEBUG
  168.     val = 1;
  169.     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0)
  170.         dprintf(L_ERROR, "setsockopt failed: %s\n", strerror(errno));
  171. #endif
  172.  
  173. #ifdef SO_SNDBUF
  174.     {
  175.         int sblen, rblen;
  176.  
  177.         /* 1024 for rpc & transport overheads */
  178.         sblen = rblen = socksz + 1024;
  179.         if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sblen, sizeof sblen) < 0 ||
  180.             setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rblen, sizeof rblen) < 0)
  181.             dprintf(L_ERROR, "setsockopt failed: %s\n", strerror(errno));
  182.     }
  183. #endif                /* SO_SNDBUF */
  184.  
  185.     if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) {
  186.         dprintf(L_ERROR, "Could not bind name to socket: %s\n",
  187.                     strerror(errno));
  188.         return (-1);
  189.     }
  190.     return (s);
  191. }
  192.  
  193.